package com.peoit.honeycomb.rest;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.peoit.honeycomb.application.SmsApplication;
import com.peoit.honeycomb.application.UserApplication;
import com.peoit.honeycomb.domain.SmsTemplate;
import com.peoit.honeycomb.domain.User;
import com.peoit.honeycomb.domain.exception.DuplicatedEmailException;
import com.peoit.honeycomb.domain.exception.DuplicatedMobileException;
import com.peoit.honeycomb.domain.exception.DuplicatedUserNameException;
import com.peoit.honeycomb.domain.exception.EmailExistException;
import com.peoit.honeycomb.domain.exception.LoginFailureException;
import com.peoit.honeycomb.domain.exception.UserNotExistException;
import com.peoit.honeycomb.domain.exception.WrongPasswordException;
import com.peoit.honeycomb.dto.ChangeUserPasswordDto;
import com.peoit.honeycomb.dto.CommonResultDto;
import com.peoit.honeycomb.dto.Config;
import com.peoit.honeycomb.dto.UserDto;
import com.peoit.honeycomb.dto.UserRealNameVerifyDto;
import com.peoit.honeycomb.util.CommonUtil;

/**
 * Created by Bing.Zeng on 2015/9/23.
 */
@Controller
@RequestMapping("/api/user")
public class UserResource extends BaseResource {
	Logger logger = Logger.getLogger(UserResource.class.getName());
	@Autowired
	UserApplication userApplication;
	@Autowired
	SmsApplication smsApplication;

	/**
	 * 用户登录，loginId可以是用户名和手机号
	 * 
	 * @param loginId
	 * @param password
	 * @return
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto login(String loginId, String password) {
		CommonResultDto result = new CommonResultDto();
		try {

			User user = userApplication.login(loginId, password);
			UserDto dto = UserDto.toDto(user);

			result.setReason("success");
			result.setResult_code("200");
			result.setResult(dto);

		} catch (LoginFailureException ex) {
			ex.printStackTrace();
			result.setReason("Username & password no match");
			result.setResult_code("404");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");
		}
		return result;

	}

	/**
	 * 用户注册
	 * 
	 * @param dto
	 * @return
	 */
	@RequestMapping(value = "/createUser", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto register(UserDto dto) {
		CommonResultDto result = new CommonResultDto();
		try {
			User user = UserDto.toUser(dto);
			user.setIsRealNameValidated(Config.not_verified);
			user.setId(UUID.randomUUID().toString());

			user = userApplication.register(user);
			dto = UserDto.toDto(user);

			result.setReason("success");
			result.setResult_code("200");
			result.setResult(dto);

		} catch (DuplicatedMobileException ex) {
			ex.printStackTrace();
			result.setReason("duplicated mobile number");
			result.setResult_code("401");
		} catch (DuplicatedUserNameException ex) {
			ex.printStackTrace();
			result.setReason("duplicated user name  ");
			result.setResult_code("403");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");
		}
		return result;

	}

	/**
	 * 提交实名认证
	 * 
	 * @param userId
	 * @param caption
	 * @return
	 */
	@RequestMapping(value = "/identify", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto identify(String userId, String caption) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);
			logger.info(" Caption : " + caption);

			userApplication.changeCaption(userId, caption);
			result.setReason("success");
			result.setResult_code("200");

		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 验证手机号码是否存在
	 * 
	 * @param phoneNumber
	 * @return
	 */
	@RequestMapping(value = "/phoneValidate", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto phoneNumberValidate(String phoneNumber) {
		CommonResultDto result = new CommonResultDto();
		try {
			boolean exist = userApplication.checkPhoneNumberExist(phoneNumber);

			if (exist) {
				result.setReason("Phone number exist");
				result.setResult_code("401");
			} else {
				result.setReason("success");
				result.setResult_code("200");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");
		}
		return result;

	}

	/**
	 * 用户名是否存在
	 * 
	 * @param userName
	 * @return
	 */
	@RequestMapping(value = "/userNameValidate", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto userNameValidate(String userName) {
		CommonResultDto result = new CommonResultDto();
		try {
			boolean exist = userApplication.checkUserNameExist(userName);

			if (exist) {
				result.setReason("User name exist");
				result.setResult_code("401");
			} else {
				result.setReason("success");
				result.setResult_code("200");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");
		}
		return result;
	}

	/**
	 * 获取手机验证码
	 * 
	 * @param phoneNumber
	 * @return
	 */
	@RequestMapping(value = "/identifyingCode", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto getIdentifyingCode(HttpServletRequest request, String phoneNumber) {
		CommonResultDto result = new CommonResultDto();
		Map<String, Object> map = new HashMap<>();
		try {
			SmsTemplate template = userApplication.getSmsTemplate("A");
			// 产生验证码
			String code = CommonUtil.get(template.getLength());
			if (StringUtils.isEmpty(template.getProduct())) {
				template.setProduct(null);
			}
			if (StringUtils.isEmpty(template.getExtno())) {
				template.setExtno(null);
			}
			template.setMsg(template.getMsg() + code);
			smsApplication.batchSend(template, phoneNumber);

			result.setResult_code("200");
			result.setReason("success");
			result.setResult(template);
			map.put("code", code);
			map.put("generateDate", new Date());
			request.getSession().setAttribute("phoneCode", map);
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setResult_code("500");
			result.setReason("Internal Error");
		}
		return result;
	}

	/**
	 * 验证手机验证码
	 * 
	 * @param phoneNumber
	 * @param validateCode
	 * @return
	 */
	@RequestMapping(value = "/validateCode", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto validateCode(HttpServletRequest request, String phoneNumber,
			String validateCode) {
		CommonResultDto result = new CommonResultDto();
		Map<String, Object> map = new HashMap<>();
		try {
			Map<String, Object> code = (Map<String, Object>) request.getSession().getAttribute("phoneCode");
			Date orginalDate = (Date) code.get("generateDate");
			Date compareDate = new Date();
			long interval = (compareDate.getTime() - orginalDate.getTime()) / 1000;
			SmsTemplate t = userApplication.getSmsTemplate("A");
			if (code.get("code").toString().equals(validateCode) && interval <= t.getFailureTime()) {
				result.setReason("success");
				result.setResult_code("200");
			} else {
				if (interval >= t.getFailureTime()) {
					result.setReason("验证码已失效，请重新生成!");
					result.setResult_code("406");
				} else {
					result.setReason("验证码不正确!");
					result.setResult_code("405");
				}
			}
		} catch (Exception ex) {
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");
		}
		return result;
	}

	/**
	 * 修改密码或者授权密码
	 * 
	 * @param dto
	 * @return
	 */
	@RequestMapping(value = "/changePassword", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto changePassword(ChangeUserPasswordDto dto) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + dto.getId());
			logger.info(" OldPassword : " + dto.getOldPassword());
			logger.info(" NewPassword : " + dto.getNewPassword());
			logger.info(" PasswordType : " + dto.getPasswordType());

			if (Config.AUTH_CODE.equals(dto.getPasswordType())) {
				userApplication.changeAuthCode(dto.getId(), dto.getOldPassword(), dto.getNewPassword());
				result.setReason("success");
				result.setResult_code("200");
			} else if (Config.LOGIN_PASS.equals(dto.getPasswordType())) {
				userApplication.changeLoginPass(dto.getId(), dto.getOldPassword(), dto.getNewPassword());
				result.setReason("success");
				result.setResult_code("200");
			} else {
				result.setReason("wrong password type");
				result.setResult_code("401");
			}
		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (WrongPasswordException ex) {
			result.setReason("wrong pass");
			result.setResult_code("403");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 重置密码和授权密码
	 * 
	 * @param dto
	 * @return
	 */
	@RequestMapping(value = "/resetPassword", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto resetPassword(ChangeUserPasswordDto dto) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + dto.getId());
			logger.info(" NewPassword : " + dto.getNewPassword());
			logger.info(" PasswordType : " + dto.getPasswordType());

			if (Config.AUTH_CODE.equals(dto.getPasswordType())) {
				userApplication.resetAuthCode(dto.getId(), dto.getNewPassword());
				result.setReason("success");
				result.setResult_code("200");
			} else if (Config.LOGIN_PASS.equals(dto.getPasswordType())) {
				userApplication.resetLoginPass(dto.getId(), dto.getNewPassword());
				result.setReason("success");
				result.setResult_code("200");
			} else {
				result.setReason("wrong password type");
				result.setResult_code("401");
			}
		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 验证AuthorizationCode
	 * 
	 * @param loginId
	 * @return
	 */
	@RequestMapping(value = "/veifyAuthorizationCode", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto veifyAuthorizationCode(String loginId, String authorizationCode) {
		CommonResultDto result = new CommonResultDto();
		try {
			boolean success = userApplication.verifyAuthorizationCode(loginId, authorizationCode);
			if (success) {
				result.setReason("success");
				result.setResult_code("200");
			} else {
				result.setReason("wrong authorizationcode");
				result.setResult_code("401");
			}
		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception e) {
			result.setReason("internal error: " + e.getMessage());
			result.setResult_code("500");
		}
		return result;
	}

	/**
	 * 修改头像
	 * 
	 * @param userId
	 * @param avatarFile
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/changeAvatar", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto changeAvatar(String userId,
			@RequestParam(value = "avatarFile", required = false) MultipartFile avatarFile,
			HttpServletRequest request) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);

			String filePath = storeUploadFile(request, avatarFile);
			userApplication.changeAvatar(userId, filePath);
			result.setReason("success");
			result.setResult_code("200");

		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 修改手机号码
	 * 
	 * @param userId
	 * @param mobile
	 * @return
	 */
	@RequestMapping(value = "/changeMobile", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto changeMobile(String userId, String mobile) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);
			logger.info(" Mobile : " + mobile);

			userApplication.changeMobile(userId, mobile);
			result.setReason("success");
			result.setResult_code("200");

		} catch (DuplicatedMobileException ex) {
			result.setReason("Mobile exists");
			result.setResult_code("401");
		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 修改邮箱
	 * 
	 * @param userId
	 * @param email
	 * @return
	 */
	@RequestMapping(value = "/changeEmail", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto changEmail(String userId, String email) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);
			logger.info(" Email : " + email);

			userApplication.changeEmail(userId, email);
			result.setReason("success");
			result.setResult_code("200");

		} catch (DuplicatedEmailException ex) {
			result.setReason("Email exists");
			result.setResult_code("401");
		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 验证邮箱
	 * 
	 * @param email
	 * @return
	 */
	@RequestMapping(value = "/verifyEmail", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto verifyEmail(String email) {
		CommonResultDto result = new CommonResultDto();
		try {
			result.setReason("success");
			result.setResult_code("200");
			userApplication.verifyEmail(email);
		} catch (EmailExistException ex) {
			result.setReason("Email exist");
			result.setResult_code("406");
		} catch (Exception ex) {
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;

	}

	/**
	 * 修改用户简介
	 * 
	 * @param userId
	 * @param caption
	 * @return
	 */
	@RequestMapping(value = "/changeUserCaption", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto changeUserCaption(String userId, String caption) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);
			logger.info(" Caption : " + caption);

			userApplication.changeCaption(userId, caption);
			result.setReason("success");
			result.setResult_code("200");

		} catch (UserNotExistException ex) {
			result.setReason("user not exist");
			result.setResult_code("402");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 用户实名认证
	 * 
	 * @param idFrontFile
	 * @param idBackFile
	 * @param dto
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/verifyId", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto verifyId(
			@RequestParam(value = "idFrontFile", required = false) MultipartFile idFrontFile,
			@RequestParam(value = "idBackFile", required = false) MultipartFile idBackFile, UserRealNameVerifyDto dto,
			HttpServletRequest request) {
		CommonResultDto result = new CommonResultDto();
		try {

			// 依次处理处理各个上传文件

			String idFrontFilePath = this.storeUploadFile(request, idFrontFile);
			String idBackFilePath = this.storeUploadFile(request, idBackFile);

			dto.setIdCardFrontFile(idFrontFilePath);
			dto.setIdCardBackFile(idBackFilePath);

			userApplication.verifyID(dto);

			result.setReason("success");
			result.setResult_code("200");
		} catch (UserNotExistException ex) {
			ex.printStackTrace();
			result.setReason("User not exist");
			result.setResult_code("404");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");
		}
		return result;

	}

	/**
	 * 验证用户是否通过实名认证
	 * 
	 * @param userId
	 * @return
	 */
	@RequestMapping(value = "/isVerified", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto isVerified(String userId) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);

			User user = userApplication.find(User.class, userId);

			if (user == null) {
				result.setReason("user not exist");
				result.setResult_code("402");
			} else {
				Map<String, String> map = new HashMap<>();
				map.put("isVerified", user.getIsRealNameValidated());
				result.setResult(map);
				result.setReason("success");
				result.setResult_code("200");
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}

	/**
	 * 获取用户等级
	 * 
	 * @param userId
	 * @return
	 */
	@RequestMapping(value = "/getUserLevel", method = RequestMethod.POST)
	public @ResponseBody CommonResultDto getUserLevel(String userId) {
		CommonResultDto result = new CommonResultDto();
		try {
			logger.info(" UserId : " + userId);

			Map<String, String> resultMap = userApplication.getUserLevel(userId);

			result.setReason("success");
			result.setResult_code("200");
			result.setResult(resultMap);

		} catch (UserNotExistException ex) {
			ex.printStackTrace();
			result.setReason("User not exist");
			result.setResult_code("404");
		} catch (Exception ex) {
			ex.printStackTrace();
			result.setReason("internal error: " + ex.getMessage());
			result.setResult_code("500");

		}
		return result;
	}
}